<?
function Templater($templatename, $dao=Array())
{
	// read template file
	$content = GetSiteTemplate($templatename."/".$templatename);
	
	// start recursive parsing of template
	$content = TemplaterParse($content, $dao);
	
	return $content;
}


function TemplaterParse($content,$dao=Array())
{
	global $CONFIG;
	// search for structural blocks: for, if, echo
	$beg=TemplaterNextTag($content);
	$end=strpos($content,"}",$beg);
	
	while( is_int($beg) && is_int($end) ) //&& ($end>$beg) )
	{
		$tag = substr($content, $beg+1, ($end-$beg)-1);
		
		$space = strpos($tagname," ");
		$tagname = ( is_int($space) ? substr($tag,0,$space) : $tag);
		
		if($tagname!="echo")
		{
			$beg2 = TemplaterFindClosingTag($content, $tagname);
			$end2 = strpos($content,"}",$beg2);
		}
		else
			$end2=$end;
		
		$taginside = substr( $content, $end+1, ($beg2-$end-1) );
		
		switch($tagname)
		{
			case "for":
				$content = substr($content,0,$beg).TemplaterFor($tag,$taginside,$dao).substr($content,$end2+1);
				break;
			case "if":
				$content = substr($content,0,$beg).TemplaterIf($tag,$taginside,$dao).substr($content,$end2+1);
				break;
			case "echo":
				$content = substr($content,0,$beg).TemplaterEcho($tag,$taginside,$dao).substr($content,$end2+1);
				break;
		}
		
		$beg=TemplaterNextTag($content);
		$end=strpos($content,"}",$beg);
	}
	
	// apply engines
	$beg=strpos($content,"<#");
	$end=strpos($content,"#>",$beg);
	
	while( is_int($beg) && is_int($end) )
	{
		$tag = substr($content, $beg+2, ($end-$beg)-2);
		$content = substr($content,0,$beg). TemplaterEngine($tag,$dao) .substr($content,$end+2);
		
		$beg=strpos($content,"<#");
		$end=strpos($content,"#>",$beg);
	}
	
	
	$content = str_replace("<*pagetitle*>",$CONFIG["pagetitle"],$content);
	$content = str_replace("<*pagetitle_ext*>",($CONFIG["pagetitle_ext"]?$CONFIG["pagetitle_ext"]:$CONFIG["pagetitle"]),$content);
	$content = str_replace("<*keywords*>", $CONFIG["keywords"],$content);
	// insert data from dao
	foreach($dao as $k=>$v)
	{
		$content = str_replace("<*".$k."*>",$v,$content);
	}
	
	return $content;
}


function TemplaterFor($tag,$taginside,$dao)
{
	$split = SplitTag($tag);
	$tagname = $split[0];
	$params  = $split[1];
	
	$source = $dao[ $params["source"] ];
	
	if($params["order"]=="inverse") $source=array_reverse($source);
	if($params["order"]=="shuffle") shuffle($source);
	
	$i=1;
	if(!is_array($source)) return '';
	foreach($source as $row)
	{
		$row["i"]=&$i;
		$row["for_first"]=($i==1);
		$row["for_last"]=($i==sizeof($source));
		$row["for_count"]=sizeof($source);
		
		/* aliases for numeric indexes */
		$row["item_0"]=$row[0];
		$row["item_1"]=$row[1];
		
		$content.= TemplaterParse($taginside, array_merge($dao,$row));
		
		$i++;
	}
	return $content;
}

function TemplaterIf($tag,$taginside,$dao)
{
	// check - do we have a condition itself
	if( !is_int(strpos($tag," ")) ) return;
	// separate if from else
	$elsebeg=TemplaterFindElse($taginside);
	if( is_int($elsebeg) ) 
	{
		$ret = substr($taginside,$elsebeg+6);
		$taginside = substr($taginside,0,$elsebeg);
	}
	// set the variable scope
	foreach($dao as $k=>$v)
	{
		$$k = $v;
	}
	// get the condition
	$cond = substr($tag,strpos($tag," "));
	// check it
	eval('if('.$cond.') $ret=$taginside;');
	return $ret;
}

function TemplaterEcho($tag,$taginside,$dao)
{
	// set the variable scope
	foreach($dao as $k=>$v)
	{
		$$k = $v;
	}
	// get the expression
	$exp = substr($tag,strpos($tag," "));
	// execute it
	eval('$ret='.$exp.';');
	return $ret;
}


function TemplaterFindElse($content)
{
	$start=0;
	$childtags=0;
	
	$len=strlen($content);
	while( $start<$len )
	{
		$beg=strpos($content,"{if",$start);
		$beg1=strpos($content,"{/if",$start);
		$beg2=strpos($content,"{else",$start);
		
		if ( !is_int($beg2)) return $beg2; //false
		
		if ( is_int($beg) && is_int($beg1) && $beg<$beg1 && $beg<$beg2) { $childtags++;$start=$beg+1;}
		
		if( $childtags==0 && is_int($beg2) ) return $beg2;
		
		if ( is_int($beg) && is_int($beg1) && $beg1<$beg) { $childtags--;$start=$beg1+1;};
		if ( !is_int($beg) && is_int($beg1)) { $childtags--;$start=$beg1+1;};
		if ( is_int($beg) && !is_int($beg1)) return $beg1;  //false
		if ( !is_int($beg) && !is_int($beg1)) return $beg1; //false
	}
	
	return "";
}

function TemplaterFindClosingTag($content,$tagname,$start=0)
{
	$childtags=0;
	
	$beg=strpos($content,"{/".$tagname."}",$start);
	$beg2=strpos($content,"{".$tagname,$start);
	
	if ( !($beg2===false)  &&  ($beg2<$beg) ) {$childtags++;$start=$beg2+1;}
	
	while($childtags>0 )
	{
		$beg=strpos($content,"{/".$tagname."}",$start);
		$beg2=strpos($content,"{".$tagname,$start);
		$start=min($beg,$beg2)+1;
		
		if( !($beg2===false)  &&  ($beg2<$beg) ) {$childtags++;$start=$beg2+1;}
		else {$childtags--;$start=$beg+1;}
	}
	
	return $beg;
}


function TemplaterEngine($tag,$dao)
	{
		// get tag's params, if exists
		$split = SplitTag($tag);
		$tagname = $split[0];
		$params  = $split[1];
		
		// include class
		if(!class_exists($tagname) )
		{
			$tname=$tagname;
			if(is_int(strpos($tname,"_")))	$tname=substr($tname,0,strpos($tname,"_"));
			if($tname=="mainmenu") $tname="menu";
			@include_once("modules/{$tname}/{$tname}.php");
		}
		if(!class_exists($tagname) ) return "";
		
		// create object for engine
		eval('$tag_engine = new '.$tagname.';');
		
		// set it's params
		foreach($params as $key=>$value)
		{
			if($value[0]=='$') $value=$dao[substr($value,1)];
			eval('$tag_engine->'.$key.' = "'.$value.'";');
		}
		
		return $tag_engine->Render($dao);
	}


function TemplaterNextTag($content)
{
	$begs = array();
	$begs[] = strpos($content,"{for");
	$begs[] = strpos($content,"{if");
	$begs[] = strpos($content,"{echo");
	
	$allempty=true;
	foreach($begs as $k=>$beg)
	{
		if(is_int($beg)) $allempty=false;
		else $begs[$k]=16000000; // kind of maximum number :)
	}
	if($allempty) return false;
	return min($begs);
}


function SplitTag($tag)
{
	$params = array();
	if(!is_int(strpos($tag," "))) return array($tag,$params);
	else
	{
		$tagname=substr($tag,0,strpos($tag," "));
		$tag=substr($tag,strpos($tag," ")+1);
		
		$len=strlen($tag);
		$newparam="";
		$newval="";
		$i=0;
		$inquotes=false;
		$inval=false;
		while($i<$len)
		{
			if(!$inval)
			{
				if($tag[$i]!="=") $newparam.=$tag[$i];
				else 
				{
					$inval=true;
					if($tag[$i+1]=='"') {$i++; $inquotes=true;}
				}
			}
			else
			{
				if($inquotes)
				{
					if($tag[$i]!='"') $newval.=$tag[$i];
					else
					{
						$params[$newparam]=$newval;
						$newval="";
						$newparam="";
						$inval=false;
						$inquotes=false;
						if( $i+1 < $len && $tag[$i+1]==" ") $i++;
					}
				}
				else
				{
					if($tag[$i]!=" ") $newval.=$tag[$i];
					else
					{
						$params[$newparam]=$newval;
						$newval="";
						$newparam="";
						$inval=false;
					}
				}
			}
			
			$i++;
		}
		if($newparam && $newval) $params[$newparam]=$newval;
	}
	return array($tagname,$params);
}